package com.quanyan.stadium.service.gameEventScore.impl;

import com.alibaba.dubbo.common.utils.CollectionUtils;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.quanyan.stadium.biz.BizGameSystemDao;
import com.quanyan.stadium.constants.GameConstants;
import com.quanyan.stadium.entity.*;
import com.quanyan.stadium.entity.vo.VDefinedGameScheduleScore;
import com.quanyan.stadium.mapper.VStadiumUserDefinedMapper;
import com.quanyan.stadium.service.commonComponent.GameMQProduct;
import com.quanyan.stadium.service.gameEventScore.GameScoreService;
import com.quanyan.stadium.service.gameRules.GameSystemServiceEight;
import com.quanyan.stadium.transfer.GameConfigTransfer;
import com.quanyan.stadium.utils.GameCategoryScoreUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.*;

/**
 * @author songzj
 * @date 16/4/11-14:42
 */

@Service("GameScoreServiceImpl")
public class GameScoreServiceImpl implements GameScoreService {

    @Autowired
    private BizGameSystemDao bizGameSystemDao;

    @Autowired
    private GameSystemServiceEight gameSystemServiceEight;

    @Autowired
    private VStadiumUserDefinedMapper vStadiumUserDefinedMapper;

    @Autowired
    private GameMQProduct gameMQProduct;

    @Autowired
    private GameConfigTransfer gameEventTransfer;

    private static final Logger logger = LoggerFactory.getLogger(GameScoreServiceImpl.class);


    @Override
    public void gameTeamRankList(TbGameEvent tbGameEvent) {
        List<TbGameEventScore> gameEventScores = this.initTeamRankByGameEventId(tbGameEvent);
        if (CollectionUtils.isNotEmpty(gameEventScores)) {
            for (TbGameEventScore score : gameEventScores) {  //进行积分计算
                if (tbGameEvent.getGameTeamType().equals(GameConstants.TEAM_TYPE_CLUB)) {
                    score.setScore(GameCategoryScoreUtils.getUserCategoryScore(GameCategoryScoreUtils.getOfficialGameEventK(tbGameEvent.getGameEventType()),
                            1, gameEventScores.size(), score.getRank(), tbGameEvent.getStartTime()));
                }else if (tbGameEvent.getGameTeamType().equals(GameConstants.TEAM_TYPE_PERSON)) {
                    int rank = score.getRank();
                    if (gameEventTransfer.getGameCategoryById(tbGameEvent.getGameCategoryType().intValue()).getMinNum() == 2
                            && gameEventTransfer.getGameCategoryById(tbGameEvent.getGameCategoryType().intValue()).getMaxNum() == 2) {
                        rank = rank%2==0?rank/2:rank/2+1;
                    }
                    score.setScore(GameCategoryScoreUtils.getUserCategoryScore(GameCategoryScoreUtils.getOfficialGameEventK(tbGameEvent.getGameEventType()),
                            1, gameEventScores.size(), rank, tbGameEvent.getStartTime()));
                }
                bizGameSystemDao.insertTbGameEventScore(score);
            }
        }
        gameMQProduct.gameEventFinishStartPushMsgMQ(tbGameEvent);
        gameMQProduct.gameEventFinishStartCollectMsgMQ(tbGameEvent);
        gameMQProduct.gameEventFinishCumsumScoreMQ(tbGameEvent);
        gameMQProduct.gameEventFinishScoreCategoryMQ(tbGameEvent);
    }

    /**
     * 根据赛制对积分排名处理
     *
     * */
    private List<TbGameEventScore> initTeamRankByGameEventId(TbGameEvent tbGameEvent) {
        List<TbGameRound> tbGameRoundList = bizGameSystemDao.selectTbGameRoundByGameEventId(tbGameEvent.getId());
        Collections.sort(tbGameRoundList, new Comparator<TbGameRound>() {   //按轮次的先后排序,id最大的为最后一轮
            public int compare(TbGameRound o1, TbGameRound o2) {
                return o2.getId().compareTo(o1.getId());
            }
        });

        List<TbGameEventTeam> teams = bizGameSystemDao.selectTbGameEventTeamByGameEventId(tbGameEvent.getId(), GameConstants.IS_NOT_DELETE);
        Map<Integer, TbGameEventTeam> teamMap = new HashMap<>();
        for (TbGameEventTeam tbGameEventTeam:teams) {
            teamMap.put(tbGameEventTeam.getId(), tbGameEventTeam);
        }
        List<TbGameEventScore> tbGameEventScores = new ArrayList<>();   //封装用户信息
        switch (tbGameEvent.getGameSystemType()) {
            case 1:
                tbGameEventScores = this.initTeamRankTypeLastRound(tbGameEvent, tbGameRoundList, teamMap);
                break;
            case 2:
                tbGameEventScores = this.initTeamRankTypeLastRound(tbGameEvent, tbGameRoundList, teamMap);
                break;
            case 3:
                tbGameEventScores = this.initTeamRankTypeLastRound(tbGameEvent, tbGameRoundList, teamMap);
                break;
            case 4:
                tbGameEventScores = this.initTeamRankTypeLastRound(tbGameEvent, tbGameRoundList, teamMap);
                break;
            case 5:
                //对抗赛, 不予受理
                //tbGameEventScores = this.initTeamRankTypeSign(tbGameEvent, tbGameRoundList, teamMap);
                break;
            case 6:
                //tbGameEventScores = this.initTeamRankTypeSign(tbGameEvent, tbGameRoundList, teamMap);
                break;
            case 7:
                tbGameEventScores = this.initTeamRankTypeSign(tbGameEvent, tbGameRoundList, teamMap);
                break;
            default:
                break;
        }

        return tbGameEventScores;
    }

    /**
     * 普通的排名,根据最后一轮的积分和队伍报名先后顺序进行排名
     *
     * */
    private List<TbGameEventScore> initTeamRankTypeLastRound(TbGameEvent tbGameEvent, List<TbGameRound> tbGameRoundList, Map<Integer, TbGameEventTeam> teamMap){
        List<TbGameRoundScore> lastRoundScoreList = bizGameSystemDao.selectTbGameRoundScoreByGameRoundId(tbGameRoundList.get(0).getId(), null, null);
        Map<Integer, TbGameRoundScore> map = new HashMap<>();
        for (TbGameRoundScore tb : lastRoundScoreList) {
            map.put(tb.getGameEventTeamId(), tb);
        }
        List<TeamScoreRank> teamScoreRankList = new ArrayList<>();
        for (int i=0;i<lastRoundScoreList.size();i++) {         //排序
            TeamScoreRank teamScoreRank = new TeamScoreRank();
            teamScoreRank.setId(lastRoundScoreList.get(i).getGameEventTeamId());
            teamScoreRank.setBigScore(lastRoundScoreList.get(i).getScore());
            teamScoreRankList.add(this.getAllOpponentScore(teamScoreRank, lastRoundScoreList.get(i).getGameEventTeamId(), map));
        }

        Collections.sort(teamScoreRankList, new Comparator<TeamScoreRank>() {
            public int compare(TeamScoreRank o1, TeamScoreRank o2) {
                int i = o2.getBigScore().compareTo(o1.getBigScore());   //大分
                if(i==0){
                    int j=o2.getOpponentScore().compareTo(o1.getOpponentScore());   //对手分
                    if(j==0){
                        return o2.getSmallScore().compareTo(o1.getSmallScore());    //小分
                    }
                    return j;
                }
                return i;
            }
        });
        List<TbGameEventScore> tbGameEventScores = new ArrayList<>();   //封装用户信息
        for (int i=0;i<teamScoreRankList.size();i++) {
            TbGameEventScore gameEventTeamScore = new TbGameEventScore();
            TbGameRoundScore tbGameRoundScore = map.get(teamScoreRankList.get(i).getId());
            gameEventTeamScore.setCategoryId(tbGameEvent.getCategoryId());
            gameEventTeamScore.setPlaceId(tbGameEvent.getPlaceId());
            gameEventTeamScore.setGameEventId(tbGameEvent.getId());
            gameEventTeamScore.setGameEventTeamId(tbGameRoundScore.getGameEventTeamId());
            gameEventTeamScore.setType(tbGameEvent.getType());
            gameEventTeamScore.setMemberTime(new Date());
            gameEventTeamScore.setProducts(tbGameRoundScore.getProducts());
            gameEventTeamScore.setWins(tbGameRoundScore.getWins());
            gameEventTeamScore.setTies(tbGameRoundScore.getTies());
            gameEventTeamScore.setFails(tbGameRoundScore.getFails());
            gameEventTeamScore.setOriginalScore(tbGameRoundScore.getScore());
            gameEventTeamScore.setOpponentScore(teamScoreRankList.get(i).getOpponentScore());
            gameEventTeamScore.setSmallScore(teamScoreRankList.get(i).getSmallScore());
            if (tbGameEvent.getGameTeamType().equals(GameConstants.TEAM_TYPE_CLUB)) {
                gameEventTeamScore.setClubId(teamMap.get(tbGameRoundScore.getGameEventTeamId()).getClubId());
            }else if (tbGameEvent.getGameTeamType().equals(GameConstants.TEAM_TYPE_PERSON)) {
                gameEventTeamScore.setUid(teamMap.get(tbGameRoundScore.getGameEventTeamId()).getUid());
            }
            gameEventTeamScore.setRank(i+1);
            tbGameEventScores.add(gameEventTeamScore);
        }
        return tbGameEventScores;
    }

    /**
     * 特殊的排名,根据签位置来排名
     *
     * 这里可以解决抢钱赛最后签位不交换的问题
     *
     * */
    private List<TbGameEventScore> initTeamRankTypeSign(TbGameEvent tbGameEvent, List<TbGameRound> tbGameRoundList, Map<Integer, TbGameEventTeam> teamMap){
        List<TbGameSchedule> scheduleList = bizGameSystemDao.selectTbGameScheduleByGameRoundId(tbGameRoundList.get(0).getId(), null, null);
        List<Integer> newTeamIds = new ArrayList<>();
        for (TbGameSchedule tbGameSchedule : scheduleList) {
            if (tbGameSchedule.getIsWin().intValue() == GameConstants.SCHEDULE_LOSE.intValue()) {
                Gson gson = new Gson();
                List<Integer> tempTeam = gson.fromJson(tbGameSchedule.getTeamListIndex(), new TypeToken<List<Integer>>() {
                }.getType());
                List<Integer> tempLocation = gson.fromJson(tbGameSchedule.getTeamMatchIndex(), new TypeToken<List<Integer>>() {
                }.getType());
                newTeamIds = gameSystemServiceEight.eightChangeLocation(tempTeam, tempLocation);
            }
        }
        Map<Integer, Integer> mapRank = new HashMap<>();
        for (int j=0;j<newTeamIds.size(); j++) {
            mapRank.put(newTeamIds.get(j), j);
        }

        List<TbGameRoundScore> lastRoundScoreList = bizGameSystemDao.selectTbGameRoundScoreByGameRoundId(tbGameRoundList.get(0).getId(), null, null);
        Map<Integer, TbGameRoundScore> map = new HashMap<>();
        for (TbGameRoundScore tb : lastRoundScoreList) {
            map.put(tb.getGameEventTeamId(), tb);
        }

        List<TbGameEventScore> tbGameEventScores = new ArrayList<>();   //封装用户信息
        for (int i=0;i<lastRoundScoreList.size();i++) {
            TbGameEventScore gameEventTeamScore = new TbGameEventScore();
            gameEventTeamScore.setCategoryId(tbGameEvent.getCategoryId());
            gameEventTeamScore.setPlaceId(tbGameEvent.getPlaceId());
            gameEventTeamScore.setGameEventId(tbGameEvent.getId());
            gameEventTeamScore.setGameEventTeamId(lastRoundScoreList.get(i).getId());
            gameEventTeamScore.setType(tbGameEvent.getType());
            gameEventTeamScore.setMemberTime(new Date());
            gameEventTeamScore.setProducts(lastRoundScoreList.get(i).getProducts());
            gameEventTeamScore.setWins(lastRoundScoreList.get(i).getWins());
            gameEventTeamScore.setTies(lastRoundScoreList.get(i).getTies());
            gameEventTeamScore.setFails(lastRoundScoreList.get(i).getFails());
            gameEventTeamScore.setOriginalScore(lastRoundScoreList.get(i).getScore());
            if (tbGameEvent.getGameTeamType().equals(GameConstants.TEAM_TYPE_CLUB)) {
                gameEventTeamScore.setClubId(teamMap.get(lastRoundScoreList.get(i).getGameEventTeamId()).getClubId());
            }else if (tbGameEvent.getGameTeamType().equals(GameConstants.TEAM_TYPE_PERSON)) {
                gameEventTeamScore.setUid(teamMap.get(lastRoundScoreList.get(i).getGameEventTeamId()).getUid());
            }
            gameEventTeamScore.setRank(mapRank.get(lastRoundScoreList.get(0).getGameEventTeamId())+1);
            tbGameEventScores.add(gameEventTeamScore);
        }

        return tbGameEventScores;
    }

    /**
     * 获取对手分 和 小分,  轮空的话 ,他的对手分去其他对手的均值
     *
     * */
    private TeamScoreRank getAllOpponentScore(TeamScoreRank teamScoreRank, int teamId, Map<Integer, TbGameRoundScore> map){
        double opponentScore = 0.0, allOpponentBigScore = 0.0, ownAllScore = 0.0, oppAllScore = 0.0;
        int notExistByeNum = 0;
        List<VDefinedGameScheduleScore> list = vStadiumUserDefinedMapper.selectVDefinedGameScheduleScore(teamId);
        if (null!=list && list.size()>0) {



            for (VDefinedGameScheduleScore vDefinedTemp:list) {
                if (vDefinedTemp.getGameEventTeamId().intValue() == teamId)
                    break;
                if (vDefinedTemp.getGameEventTeamId() >0 && null!=map.get(vDefinedTemp.getGameEventTeamId())) {
                    List<Integer> scoreList = this.getOneOpponentScore(vDefinedTemp.getGameScheduleId(), vDefinedTemp.getFinalScore());
                    if (vDefinedTemp.getType().intValue() == GameConstants.IS_NOT_DELETE.intValue()) {      //比分进行调整,根据主客队的逻辑
                        Collections.swap(scoreList, 0, 1);
                    }
                    opponentScore +=  map.get(vDefinedTemp.getGameEventTeamId()).getScore()*scoreList.get(0)/((scoreList.get(0)+scoreList.get(1))==0?1:(scoreList.get(0)+scoreList.get(1)));
                    ownAllScore += scoreList.get(0);
                    oppAllScore += scoreList.get(1);
                    notExistByeNum += 1;
                    allOpponentBigScore += map.get(vDefinedTemp.getGameEventTeamId()).getScore();
                }
            }
        }
        teamScoreRank.setOpponentScore(new BigDecimal(opponentScore + (list.size() - notExistByeNum) * (allOpponentBigScore / notExistByeNum)).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
        teamScoreRank.setSmallScore(new BigDecimal(oppAllScore==0?100.0:ownAllScore/oppAllScore).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
        return teamScoreRank;
    }

    /**
     * 对手的比分与对手大分的乘积
     *
     * */
    private List<Integer> getOneOpponentScore(int gameScheduleId, String score){
        List<Integer> scoreList = new ArrayList<>();
        try{
            String[] str = score.split(":");
            scoreList.add(Integer.parseInt(str[0]));
            scoreList.add(Integer.parseInt(str[1]));
        }catch (Exception e) {
            logger.error("解析比分错误,当前队伍赛程id:{}, 错误原因:{}", gameScheduleId, e);
        }
        return scoreList;
    }

    /**
     * Created by xiaoxiao on 16/10/8.
     *
     *  * 队伍积分排名基本对象

     */
    class TeamScoreRank implements Serializable {

        private static final long serialVersionUID = -2056544663270822677L;

        private Integer id;

        private Double bigScore;    //大分

        private Double opponentScore;   //对手分

        private Double smallScore;      //小分


        public Integer getId() {
            return id;
        }

        public void setId(Integer id) {
            this.id = id;
        }

        public Double getBigScore() {
            return bigScore;
        }

        public void setBigScore(Double bigScore) {
            this.bigScore = bigScore;
        }

        public Double getOpponentScore() {
            return opponentScore;
        }

        public void setOpponentScore(Double opponentScore) {
            this.opponentScore = opponentScore;
        }

        public Double getSmallScore() {
            return smallScore;
        }

        public void setSmallScore(Double smallScore) {
            this.smallScore = smallScore;
        }
    }
}
